/***************************************************************************
 *   Copyleft 2008-2009 by												   *
 *	 Iwanicki Krzysztof													   *
 *   <gamma.mini.pw.edu.pl/~iwanickik>									   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 ***************************************************************************/
#ifndef __VTEXTUREUNIT_H__
#define __VTEXTUREUNIT_H__

#include "./vTexture2D.h"
#include "../../Utils/vUtils.h"
#include "../../Macros/vMemoryMacros.h"

namespace Vendetta {
	/*! \class vTextureUnit
	 *  \brief A vTextureUnit class represents single texture unit info.
	 *
	 *	vTextureUnits are used by vPass for attaching textures to passes.
	 *	Represents texture mapping on models.
	 *	Objects of type vTextureUnits can only be created by vPass. User
	 *	can't create it by own.
	 *
	 *	\sa vPass.
	 *	\sa vMaterial.
	 */
	class vTextureUnit {
		friend class vPass;
	public:
		/*! \enum vTextureUnit::eBlendMode
		 *  \brief A eBlendMode enum is used for blend mode type for source and destination targets.
		 *
		 *  There are two types of blend mode:
		 *  1. VBM_ZERO - black color & target color = black color.
		 *  2. VBM_ONE - white color & target color = target color.
		 *  
		 *  Default blend mode for source target is VBM_ONE and for destination target is VBM_ZERO.
		 *  
		 */
		enum eBlendMode {
			VBM_ZERO,
			VBM_ONE
		};

		/*! \enum vTextureUnit::eAddressMode
		 *  \brief A eAddressMode enum is used for determining texture behavior.
		 *
		 *	Determines how texturu coordinate should be mapped when it is out of [0, 1] range.
		 *
		 *  There are three types of address mode:
		 *  1. VAM_REPEAT - repeats texture.
		 *  2. VAM_CLAMP - last texel mapping which is equal to 1.0 is used.
		 *  3. VAM_MIRROR - texture is mirror after crossing each boundary.
		 *  
		 *  Default address mode is VAM_REPEAT.
		 *  
		 */
		enum eAddressMode {
			VAM_REPEAT,
			VAM_CLAMP,
			VAM_MIRROR
		};

		/*! \enum eFilterMode::eAddressMode
		 *  \brief A eFilterMode enum is used for filtrating textures.
		 *
		 *	Texture filtration is used to get rid off aliasing problem.
		 *
		 *  There are four types of filter mode:
		 *  1. VFM_NONE - none filtering, aliasing problem.
		 *  2. VFM_BILINEAR - bilinear.
		 *  3. VFM_TRILINEAR - trilinear.
		 *  4. VFM_ANISOTROPIC - anisotropic.
		 *  
		 *  Default filter mode is VFM_NONE.
		 *  
		 */
		enum eFilterMode {
			VFM_NONE,
			VFM_BILINEAR,
			VFM_TRILINEAR,
			VFM_ANISOTROPIC
		};

	public:
		vVoid Apply();

		/*! \brief Sets source target blend mode.
		 *
		 *			 
		 *  \param		blendMode				Blend mode to apply to source target.
		 *	\sa			vTextureUnit::eBlendMode.
		 */
		vVoid SetSrcBlendMode(eBlendMode blendMode);

		/*! \brief Sets destination target blend mode.
		 *
		 *			 
		 *  \param		blendMode				Blend mode to apply to destination target.
		 *	\sa			vTextureUnit::eBlendMode.
		 */
		vVoid SetDstBlendMode(eBlendMode blendMode);

		/*! \brief Enables/Disables blending.
		 *
		 *	Blending is disable by default.
		 *			 
		 *  \param		bEnabled				True if blending should be enabled, false otherwise.
		 *	\sa			vTextureUnit::eBlendMode.
		 */
		vVoid SetBlending(vBool bEnabled);

		/*! \brief Sets U param address mode.
		 *
		 *	This param is used in all kind of textures.
		 *			 
		 *  \param		addressMode				Address mode to apply to U texture parameter.
		 *	\sa			vTextureUnit::eAddressMode.
		 */
		vVoid SetUAddressMode(eAddressMode addressMode);

		/*! \brief Sets V param address mode.
		 *
		 *	This param is used only in 2D and 3D and cube textures.
		 *			 
		 *  \param		addressMode				Address mode to apply to V texture parameter.
		 *	\sa			vTextureUnit::eAddressMode.
		 */
		vVoid SetVAddressMode(eAddressMode addressMode);

		/*! \brief Sets W param address mode.
		 *
		 *	This param is used only in 3D and cube textures.
		 *			 
		 *  \param		addressMode				Address mode to apply to W texture parameter.
		 *	\sa			vTextureUnit::eAddressMode.
		 */
		vVoid SetWAddressMode(eAddressMode addressMode);

		/*! \brief Set U, V, W params address mode.
		 *
		 *			 
		 *  \param		addressMode				Address mode to apply to U, V, W texture parameters.
		 *	\sa			vTextureUnit::eAddressMode.
		 */
		vVoid SetUVWAddressMode(eAddressMode addressMode);

		/*! \brief Set texture minification and magnification filter mode.
		 *
		 *
		 *  \param		filterMode				Filter mode to apply to minification and magnification.
		 *	\sa			vTextureUnit::eFilterMode.
		 */
		vVoid SetMinMagFilterMode(eFilterMode filterMode);

		/*! \brief Sets rotate angle.
		 *
		 *	Rotation is clockwise.
		 *			 
		 *  \param		rAngle					Rotate angle in degrees.
		 */
		vVoid SetRotate(vReal rAngle);

		/*! \brief Sets x direction scale factor. Scale factor is clipped to 0 if is negative.
		 *
		 *			 
		 *  \param		rScaleFactor			X scale factor.
		 */
		vVoid SetXScale(vReal rScaleFactor);

		/*! \brief Sets y direction scale factor. Scale factor is clipped to 0 if is negative.
		 *
		 *			 
		 *  \param		rScaleFactor			Y scale factor.
		 */
		vVoid SetYScale(vReal rScaleFactor);

		/*! \brief Sets x and y direction scale factor. Scale factor is clipped to 0 if is negative.
		 *
		 *			 
		 *  \param		rScaleFactor			X, Y scale factor.
		 */
		vVoid SetXYScale(vReal rScaleFactor);

		/*! \brief Attaches texture to this texture unit. Each vTextureUnit must have texture attached.
		 *
		 *			 
		 *  \param		rScaleFactor			X scale factor.
		 */
		vVoid AttachTexture(vTexture* texture);


	protected:
		/*! \brief Constructor.
		 *
		 */
		vTextureUnit();

		/*! \brief Copy constructor. Nothing happens.
		 *
		 */
		vTextureUnit(const vTextureUnit& texUnit);

		/*! \brief Destructor.
		 *
		 */
		virtual ~vTextureUnit();

		/*! \brief Assign operator. Nothing happens.
		 *
		 */
		vTextureUnit& operator=(const vTextureUnit& texUnit);

	private:
		vTexture* mpTexture;

		vBool mBlendingOn;
		eBlendMode mSrcBlendMode;
		eBlendMode mDstBlendMode;
		
		eAddressMode mUAddressMode;
		eAddressMode mVAddressMode;
		eAddressMode mWAddressMode;
		eFilterMode mMinMagFilterMode;

		//change to vPoint2D later
		vReal mXScale;
		vReal mYScale;
		vReal mRotateAngle;
	};
}

#endif // __VTEXTUREUNIT_H__
